package cn.outsourcing.supermarket.service.impl;

import cn.outsourcing.supermarket.common.PageResult;
import cn.outsourcing.supermarket.common.constants.CommonConstants;
import cn.outsourcing.supermarket.common.enums.OrderStatusEnums;
import cn.outsourcing.supermarket.common.enums.OrderTypeEnums;
import cn.outsourcing.supermarket.common.exception.SupermarketException;
import cn.outsourcing.supermarket.common.utils.DataUtils;
import cn.outsourcing.supermarket.common.utils.IPageUtils;
import cn.outsourcing.supermarket.common.utils.PageResultUtils;
import cn.outsourcing.supermarket.common.utils.StrUtils;
import cn.outsourcing.supermarket.converter.HiolabsOrderConverter;
import cn.outsourcing.supermarket.converter.HiolabsOrderGoodsConverter;
import cn.outsourcing.supermarket.converter.HiolabsUserConverter;
import cn.outsourcing.supermarket.dto.backstage.*;
import cn.outsourcing.supermarket.mapper.BackstageOrderMapper;
import cn.outsourcing.supermarket.mapper.HiolabsOrderGoodsMapper;
import cn.outsourcing.supermarket.mapper.HiolabsOrderMapper;
import cn.outsourcing.supermarket.mapper.HiolabsUserMapper;
import cn.outsourcing.supermarket.po.HiolabsOrder;
import cn.outsourcing.supermarket.po.HiolabsOrderGoods;
import cn.outsourcing.supermarket.po.HiolabsUser;
import cn.outsourcing.supermarket.service.BackstageOrderService;
import cn.outsourcing.supermarket.vo.backstage.BackstageOrdersDetailVO;
import cn.outsourcing.supermarket.vo.backstage.BackstageOrdersInfoVO;
import cn.outsourcing.supermarket.vo.hiolabs.HiolabsOrderGoodsVO;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author gzkemays
 * @since 2021/11/3 1:58
 */
@Service
public class BackstageOrderServiceImpl implements BackstageOrderService {
  @Resource HiolabsUserMapper userMapper;
  @Resource HiolabsOrderGoodsMapper orderGoodsMapper;
  @Resource HiolabsOrderMapper orderMapper;
  @Resource BackstageOrderMapper backstageOrderMapper;

  @Override
  public PageResult<BackstageOrdersInfoVO> getOrdersInfo(BackstageOrdersInfoDTO infoDTO) {
    IPageUtils<HiolabsOrder> properties = IPageUtils.<HiolabsOrder>init().properties(infoDTO);
    List<Integer> status =
        Arrays.stream(infoDTO.getStatus().split(CommonConstants.COMMA_SEPARATOR))
            .map(Integer::parseInt)
            .collect(Collectors.toList());
    String orderSn = infoDTO.getOrderSn();
    String consignee = infoDTO.getConsignee();
    IPageUtils<HiolabsOrder> pages =
        orderMapper.selectPage(
            properties,
            Wrappers.<HiolabsOrder>lambdaQuery()
                .in(HiolabsOrder::getOrderStatus, status)
                .ne(HiolabsOrder::getOrderType, OrderTypeEnums.RECHARGE.getNum())
                .like(Objects.nonNull(orderSn), HiolabsOrder::getOrderSn, orderSn)
                .like(Objects.nonNull(consignee), HiolabsOrder::getConsignee, consignee)
                .orderByDesc(HiolabsOrder::getAddTime));
    /*    List<OrdersInfoVO> ordersInfoVos =
    BackstageOrderConverterImpl.INSTANCE.converterToBoListGetVoList(
        backstageHomeMapper.getOrdersData(properties, infoDTO));*/
    List<HiolabsOrder> records = pages.getRecords();
    if (!records.isEmpty()) {
      Set<Integer> userIds =
          records.stream().map(HiolabsOrder::getUserId).collect(Collectors.toSet());
      Set<Integer> orderIds = records.stream().map(HiolabsOrder::getId).collect(Collectors.toSet());

      List<HiolabsUser> users = userMapper.selectBatchIds(userIds);
      List<HiolabsOrderGoodsVO> orderGoodsVos =
          HiolabsOrderGoodsConverter.INSTANCE.convertToVoList(
              orderGoodsMapper.selectList(
                  Wrappers.<HiolabsOrderGoods>lambdaQuery()
                      .in(HiolabsOrderGoods::getOrderId, orderIds)
                      .eq(HiolabsOrderGoods::getIsDelete, 0)));

      Set<HiolabsUser> userSet = new HashSet<>(users);
      Set<HiolabsOrderGoodsVO> orderGoodsSet = new HashSet<>(orderGoodsVos);
      List<BackstageOrdersInfoVO> collect =
          records.stream()
              .map(
                  orders -> {
                    BackstageOrdersInfoVO ordersInfoVO =
                        HiolabsOrderConverter.INSTANCE.convertToBackstageVo(orders);
                    ordersInfoVO.setOrderStatusText(
                        OrderStatusEnums.DATA_MAP.get(orders.getOrderStatus()));
                    List<HiolabsOrderGoodsVO> goodsList = new ArrayList<>();
                    for (HiolabsOrderGoodsVO hiolabsOrderGoodsVO : orderGoodsSet) {
                      if (hiolabsOrderGoodsVO.getOrderId().equals(orders.getId())) {
                        goodsList.add(hiolabsOrderGoodsVO);
                      }
                    }
                    ordersInfoVO.setGoodsList(goodsList);
                    ordersInfoVO.setGoodsCount(goodsList.size());
                    for (HiolabsUser user : userSet) {
                      if (user.getId().equals(orders.getUserId())) {
                        ordersInfoVO.setUserInfo(HiolabsUserConverter.INSTANCE.convertToVo(user));
                        break;
                      }
                    }
                    return ordersInfoVO;
                  })
              .collect(Collectors.toList());
      long size = pages.getSize();
      long total = pages.getTotal();
      BigDecimal decimal = BigDecimal.valueOf(Math.ceil((double) total / size));
      return PageResult.<BackstageOrdersInfoVO>builder()
          .pageSize(pages.getSize())
          .currentPage(pages.getCurrent())
          .totalPages(decimal.intValue())
          .count((int) pages.getTotal())
          .data(collect)
          .build();
    }
    return PageResultUtils.emptyData();
  }

  @Override
  public BackstageOrdersDetailVO getOrdersDetail(Integer ordersId) {
    BackstageOrdersInfoVO orderDetails = backstageOrderMapper.getOrderDetails(ordersId);
    orderDetails.setGoodsList(backstageOrderMapper.getOrderGoodsDetails(ordersId));
    orderDetails.setOrderStatusText(OrderStatusEnums.DATA_MAP.get(orderDetails.getOrderStatus()));
    orderDetails.setUserName(StrUtils.getStrByBase64(orderDetails.getUserName()));
    orderDetails.setAddTime(DataUtils.getTimestampAllData((long) orderDetails.getAddTime()));
    orderDetails.setPayTime(DataUtils.getTimestampAllData((long) orderDetails.getPayTime()));
    orderDetails.setShippingTime(
        DataUtils.getTimestampAllData((long) orderDetails.getShippingTime()));
    orderDetails.setConfirmTime(
        DataUtils.getTimestampAllData((long) orderDetails.getConfirmTime()));
    orderDetails.setDealdoneTime(
        DataUtils.getTimestampAllData((long) orderDetails.getDealdoneTime()));
    BigDecimal promotion = orderDetails.getOrderPrice().subtract(orderDetails.getActualPrice());
    orderDetails.setPromotionsPrice(
        promotion.compareTo(BigDecimal.ZERO) > 0 ? promotion : BigDecimal.ZERO);

    HiolabsUser user = userMapper.selectById(orderDetails.getUserId());
    return new BackstageOrdersDetailVO(
        orderDetails, HiolabsUserConverter.INSTANCE.convertToVo(user));
  }

  @Override
  public Object editPrice(BackstageEditOrderPriceDTO dto) {
    HiolabsOrder hiolabsOrder = orderMapper.selectById(dto.getOrderId());
    hiolabsOrder.setActualPrice(dto.getActualPrice());
    hiolabsOrder.setGoodsPrice(dto.getGoodsPrice());
    hiolabsOrder.setFreightPrice(dto.getFreightPrice());
    hiolabsOrder.setOrderSn(StrUtils.generateOrderSn());
    int update = orderMapper.updateById(hiolabsOrder);
    if (update > 0) {
      return "OK";
    }
    throw new SupermarketException(CommonConstants.SQL_FAIL_CODE, "更新失败");
  }

  @Override
  public int changeStatus(BackstageChangeStatusDTO dto) {
    HiolabsOrder hiolabsOrder =
        orderMapper.selectOne(
            Wrappers.<HiolabsOrder>lambdaQuery().eq(HiolabsOrder::getOrderSn, dto.getOrderSn()));
    hiolabsOrder.setOrderStatus(Integer.parseInt(dto.getStatus()));
    return orderMapper.updateById(hiolabsOrder);
  }

  @Override
  public String saveGoodsList(BackstageSaveGoodsListDTO dto) {
    HiolabsOrderGoods hiolabsOrderGoods = orderGoodsMapper.selectById(dto.getId());
    hiolabsOrderGoods.setNumber(hiolabsOrderGoods.getNumber() + dto.getNumber());
    HiolabsOrder hiolabsOrder = orderMapper.selectById(hiolabsOrderGoods.getOrderId());
    Integer number = dto.getNumber();
    BigDecimal retailPrice = dto.getRetail_price();
    BigDecimal decimal =
        retailPrice.multiply(BigDecimal.valueOf(number)).setScale(2, RoundingMode.HALF_UP);
    BigDecimal actualPrice = hiolabsOrder.getActualPrice().add(decimal);
    hiolabsOrder.setActualPrice(actualPrice);
    orderMapper.updateById(hiolabsOrder);
    if (orderGoodsMapper.updateById(hiolabsOrderGoods) > 0) {
      return String.valueOf(orderMapper.selectById(hiolabsOrderGoods.getOrderId()).getOrderSn());
    }
    throw new SupermarketException(CommonConstants.SQL_FAIL_CODE, "更新失败");
  }

  @Override
  public int goDelivery(@RequestBody BackstageDeliveryDTO dto) {
    HiolabsOrder hiolabsOrder = orderMapper.selectById(dto.getOrder_id());
    hiolabsOrder.setOrderStatus(OrderStatusEnums.SHIPPED.getCode());
    hiolabsOrder.setShippingTime(DataUtils.getSeconds());
    return orderMapper.updateById(hiolabsOrder);
  }

  @Override
  public PageResult<BackstageOrdersInfoVO> userOrder(BackstageOnlyIdPageDTO dto) {
    IPageUtils<HiolabsOrder> properties = IPageUtils.<HiolabsOrder>init().properties(dto);
    // 获取用户订单信息
    List<HiolabsOrder> records =
        orderMapper
            .selectPage(
                properties,
                Wrappers.<HiolabsOrder>lambdaQuery()
                    .eq(HiolabsOrder::getUserId, dto.getId())
                    .eq(HiolabsOrder::getIsDelete, 0)
                    .orderByDesc(HiolabsOrder::getAddTime))
            .getRecords();

    List<HiolabsOrderGoods> orderGoods =
        orderGoodsMapper.selectList(
            Wrappers.<HiolabsOrderGoods>lambdaQuery()
                .eq(HiolabsOrderGoods::getUserId, dto.getId()));

    List<BackstageOrdersInfoVO> backstageOrdersInfoVos =
        HiolabsOrderConverter.INSTANCE.convertToBackstageVoList(records);

    List<BackstageOrdersInfoVO> collect =
        backstageOrdersInfoVos.stream()
            .peek(
                vo -> {
                  List<HiolabsOrderGoodsVO> ogVos = new ArrayList<>();
                  for (HiolabsOrderGoods orderGood : orderGoods) {
                    if (vo.getId().equals(orderGood.getOrderId())) {
                      ogVos.add(HiolabsOrderGoodsConverter.INSTANCE.convertToVo(orderGood));
                    }
                  }
                  vo.setGoodsList(ogVos);
                  vo.setOrderStatusText(OrderStatusEnums.DATA_MAP.get(vo.getOrderStatus()));
                  BigDecimal promotion = vo.getOrderPrice().subtract(vo.getActualPrice());
                  vo.setPromotionsPrice(
                      promotion.compareTo(BigDecimal.ZERO) > 0 ? promotion : BigDecimal.ZERO);
                })
            .collect(Collectors.toList());

    return PageResultUtils.parseListPageObjs(properties, collect);
  }
}
